#ifndef COMMAND_HPP
#define COMMAND_HPP
//
// patterns/command.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2013-2014 Razvan Coca (razvan dot coca at  gmail dot com)
// command pattern as in: http://isocpp.org/blog/2013/10/patterns
// and work-around variadic lambdas in gcc 4.7
// http://stackoverflow.com/questions/14191989/how-do-i-use-variadic-perfect-forwarding-into-a-lambda
//
//
//
#include <utility>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>

//#define _LOGGED_INSTANCES_

#if defined(_LOGGED_INSTANCES_)
#include <glog/logging.h>
#endif


namespace patterns
{
namespace command
{
typedef std::function<bool()> action_t;
typedef boost::function<bool()> boost_action_t;

/*
bool invoke(action_t& action);
bool invoke(boost_action_t& action);
*/
template<typename Action>
bool invoke(Action&& action)
{
    bool retcode=false;
    if(action) retcode=action ();
    return retcode;
}


template<typename Operation,typename... Args>
action_t wrap(boost::shared_ptr<Operation> self_,Args&& ...args)
{
    boost::weak_ptr<Operation> weak_self_(self_);
    action_t retval= std::bind([weak_self_](Args... args){
                        if(auto lself_=weak_self_.lock())
                        return lself_->exec(args...);
                        return false;
            },
            std::forward<Args>(args)...);

#if defined(_LOGGED_INSTANCES_)
    DLOG(INFO)<<__FUNCTION__<<"_"<<sizeof...(Args)<<"(&, "<<self_.use_count()<<")";
#endif
    return retval;
}



} //end namespace command
} //end namespace paterns

#endif // COMMAND_HPP
